<?php
/**
 * Класс для генерации URL адреса
 * Использует RL_RequestRouter, для конструирования используется класс реализцющий интерфейс URLDescription
 *
 * TODO: научить эту систему компилировать URL. Сейчас просто ставиться разделитель / между элементами
 * TODO: научить систему парсить и генерировать ссылки на ajax обработчики централизовано
 *
 * Сначала вся картина целиком:
 *  - RequestRouter занимается парсингом урла, поиском экземпляра класса реализующего URLDescription
 *  - URLGenerator занимается генерацией URL адреса, на входе получает класс реализующий URLDescription
 *  - пачка классов реализующих URLDescription - используется для описания правил маппинга url адресов
 *
 * Для того чтобы сгенерировать URL нужно создать экземпляр класса RL_URLGenerator,
 * на входе ему дать класс описывающий правило на основе которого будет происходить конструирование.
 *
 * $this->rh->UseClass("RL_URLGenerator"); // инклуд класса
 *
 * // создать экземпляр используя правило найденное для текущего запроса
 * // еще можно использовать $this->rh->router->getRule('object_undelete'), чтобы получить конкретное правило из массива правил
 * $ug = new RL_URLGenerator($this->rh->router->getLastMatched());
 *
 * // передаем экземпляр RequestRouter
 * $ug->setRouter($this->rh->router);
 *
 * // в обработчике. установка значений переменных-элементов парсинга урла в значения полученные при парсинге последнего правила
 * // обычный массив. ключи - имена элементов урла, значения - их значения которые будут подставлены в URL
 * $ug->setParams($this->params);
 *
 * // сказать что хочется в урл адресе видеть GET переменные. эта штука не пропустит переменную с именем page
 * $ug->setGet(array_merge($this->rh->GET, array("p"=>$this->page['prev'])));
 *
 * // сгенерировать URL.
 * var_dump( $ug->generateUrl() );
 *
 * @package default
 * @author Alexander Sibiryakov
 **/

/*

*/
class RL_URLGenerator
{
	private $rule_instance;
	var $params;
	private $get;

	private $router;
	private $is_regexp_regexp = "/[^a-zA-Z0-9:\/\-._~]/"; // этот регексп используется для проверки является ли строка рег. выражением

	/**
	 * Конструктор. Для создания URL-генератора нужно указать класс с описанием URL-адреса.
	 * В нашей системе это класс реализующий интерфейс URLDescription
	 *
	 * @return void
	 * @author Alexander Sibiryakov
	 **/
	public function __construct(URLDescription $val) {
		$this->rule_instance = $val;

		$this->rule_instance->init();

		$this->idx2params = $this->rule_instance->getURLElements();
	}

	public function setRouter(RL_RequestRouter $router) {
		$this->router = $router;
		return $this;
	}

	public function setParams(array $params) {
		$this->params = $params;
		return $this;
	}

	public function setParam ($name, $value)
	{
		$this->params[$name] = $value;
		return $this;
	} // end of method setParam

	/**
	 * Устанавливает параметры для передачи get-запросом. Они будут включены в ссылку.
	 *
	 * @return void
	 * @author Alexander Sibiryakov
	 **/
	public function setGet($val) {
		$this->get = $val;
		return $this;
	}

	public function generateUrl() {
		$url = "";
		foreach ($this->idx2params as $v) {
			// сперва поищем в параметрах которые нам прислали значение элемента урла
			if (isset($this->params[$v])) {
				if ( !empty($this->params[$v]) ) {
					$url .= $this->params[$v]."/";
				}
				continue;
			}

			// если оказались здесь, значит в параметрах нету.
			// поищем в дефолтных параметрах RL_RequestRouter
			if (array_key_exists($v, $this->router->defaults)) {
				if (preg_match($this->is_regexp_regexp , $this->router->defaults[$v])==0) {
					$url.= $this->router->defaults[$v]."/";
					continue;
				} else {
					debug("URLGenerator: cant use default param value ".$this->router->defaults[$v]);
					return false;
				}
			}

			// если в роутере нету. то проверим в параметрах описания URL-адреса
			if (array_key_exists($v, $this->rule_instance->params)) {
				// если мы что-то обнаружили,
				// то мы в состоянии сгенерировать УРЛ только если нужный нам элемент
				// при парсинге проверяется по прямому вхождению строки.
				// попытаемся удостовериться в этом проверяя наличие чего-то кроме символов букв латинского алфавита
				if (preg_match($this->is_regexp_regexp, $this->rule_instance->params[$v])==0)
				$url .= $this->rule_instance->params[$v]."/";
				else {
					debug("URLGenerator: cant use URL description param value ".$this->rule_instance->params[$v]);
					// получается не можем сгенерировать УРЛ, не достаточно данных
					return false;
				}
			}

		}

		$get_keys = '';
		if (isset($this->get)) {
			foreach($this->get as $key=>$value) {

				// хак-исключение для нашего движка
				if ($key == "page") continue;
				if (!isset($value)) continue;

				if (!is_array($value)) $get_strs[$key] = $key.($value !== true ? "=".urlencode($value) : '');
				else {
					// это массив
					foreach ($value as $i=>$j) {
						$_k = $key.urlencode("[".$i."]");
						$_v = urlencode($j);
						$get_strs[ $_k ] = $_k.($value !== true ? "=".$_v : '');
					}
				}
			}
			if ($get_strs) {
				$_p = htmlentities(implode("&", $get_strs));
				$get_keys = (strlen($_p) > 0) ? "?".$_p : "";
			} else {$get_keys = "";}
		}

		return rtrim($url, "/").$get_keys;
	}


} // END class
